package com.cjx.sec.service;

import com.cjx.sec.pojo.doo.User;
import com.cjx.sec.pojo.dto.UserDTO;
import com.cjx.sec.repository.UserRepository;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.BeanUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 用户业务层实现类
 *
 * @author cjx
 * @date 2024/8/25 13:52
 */
@Slf4j
@Service
public class UserService {
    @Resource
    private JdbcTemplate jdbcTemplate;
    @PersistenceContext
    private EntityManager entityManager;
    @Resource
    private UserRepository userRepository;
    
    /*
     * SQL拼接时，不要将参数一并拼接，要使用占位符替代，防止SQL注入。
     */
    public List<UserDTO> query(String name) {
        // 1、
        String sql = "SELECT * FROM user WHERE name = '" + name + "'";
        log.info("执行的SQL为:{}", sql);
        List<User> queryResult = jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(User.class));
        
        // 2、
//        String sql = "SELECT * FROM user WHERE name = ? ";
//        List<User> queryResult = jdbcTemplate.query(sql, new Object[]{name}, BeanPropertyRowMapper.newInstance(User.class));
        
        // 3、
//        List<User> queryResult = userRepository.findByName(name);
        
        List<UserDTO> result = queryResult.stream().map(User::buildUserDTO).collect(Collectors.toList());
        
        return result;
    }
    
    public UserDTO get(Long id) {
        Optional<User> userOp = userRepository.findById(id);
        User user = userOp.orElse(new User());
        return user.buildUserDTO();
    }
    
    @Transactional(rollbackFor = Exception.class)
    public UserDTO create(UserDTO userDTO) {
        /*
        {"name":"t1","username": "test1", "password": "123456"}
         */
        
        /*
         * 将密码加密成密文
         */
        String salt = BCrypt.gensalt();
        String pw = BCrypt.hashpw(userDTO.getPassword(), salt);
        log.info("salt: {}, pw: {}", salt, pw);
        userDTO.setPassword(pw);
//        userDTO.setPassword(SCryptUtil.scrypt(userDTO.getPassword(),2 << 14,8,1));
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        userRepository.save(user);
        userDTO.setId(user.getId());
        return userDTO;
    }
    
    @Transactional(rollbackFor = Exception.class)
    public UserDTO update(UserDTO userDTO) {
        Optional<User> userOp = userRepository.findById(userDTO.getId());
        User user = userOp.orElseThrow(() -> new RuntimeException("该用户不存在"));
        BeanUtils.copyProperties(userDTO, user);
        return userDTO;
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void batchCreate(List<UserDTO> userDTOS) {
        List<User> userList = userDTOS.stream().map(userDTO -> {
            String salt = BCrypt.gensalt();
            userDTO.setPassword(BCrypt.hashpw(userDTO.getPassword(), salt));
//        userDTO.setPassword(SCryptUtil.scrypt(userDTO.getPassword(),2 << 14,8,1));
            User user = new User();
            BeanUtils.copyProperties(userDTO, user);
            return user;
        }).collect(Collectors.toList());
        userRepository.saveAll(userList);
    }
    
    public Map<String, String> login(UserDTO userDTO, HttpServletRequest request) {
        /*
        {"username": "test1", "password": "123456"}
         */
        Map<String, String> result = Maps.newHashMap();
        
        User user = userRepository.findByUsername(userDTO.getUsername());
        if (user == null) {
            result.put("message", "用户名错误");
        } else if (!BCrypt.checkpw(userDTO.getPassword(), user.getPassword())) {
            result.put("message", "密码错误");
        } else {
            HttpSession session = request.getSession(false);
            //将之前的session失效掉
            if (session != null) {
                session.invalidate();
            }
            //将用户信息放到新的session中
            request.getSession(true).setAttribute("user", user.buildUserDTO());
            
            result.put("message", "登陆成功");
        }
        
        return result;
    }
}
